package com.mp.approvalreq.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.mp.approvalreq.dao.*;
import com.mp.approvalreq.dao.impl.*;
import com.mp.approvalreq.entity.*;
import com.mp.approvalreq.entity.GeneralRequest.GeneralRequest;
import com.mp.approvalreq.entity.common.Constants;
import com.mp.approvalreq.entity.dto.TemplateDTO;
import com.mp.approvalreq.entity.dto.TemplateInfoDTO;
import com.mp.approvalreq.entity.dto.TemplateRangeDTO;
import com.mp.approvalreq.entity.po.GlobalSetting;
import com.mp.approvalreq.service.ReadTemplateServiceServant;
import com.mp.approvalreq.util.*;
import com.mp.approvalreq.util.Formatter;
import com.mp.comment.entity.Comment;
import com.mp.user.entity.User;
import com.mp.user.service.UserServicePrx;
import com.mp.user.util.UserUtils;
import com.plusmoney.exception.RpcServerLogicalException;
import com.plusmoney.exception.enums.ApprovalRespCodeDesc;
import com.plusmoney.jdbc.util.DBUtils;
import com.plusmoney.util.Utils;
import com.qq.tars.client.util.ServantUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

public class ReadTemplateServantImpl implements ReadTemplateServiceServant {

    private static final Logger logger = LoggerFactory.getLogger(ReadTemplateServantImpl.class);

    @Override
    public List<TemplateRangeDTO> getTemplatesRange(Integer templateId, Integer defaultType, Integer companyId) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            SelectTemplateDao selectTemplateDao = DaoFactory.getSelectTemplateDao(connection);

            List<Template> templates = selectTemplateDao.getTemplatesRangeByType(defaultType, companyId);

            return initAndExcludeTemplateRangeDTO(templates, templateId);
        } catch (Throwable e) {
            logger.error(e.getMessage(), e);
            throw ErrorUtils.throwError(e);
        } finally {
            DBUtils.release(connection);
        }
    }

    private List<TemplateRangeDTO> initAndExcludeTemplateRangeDTO(List<Template> templates, Integer templateId) {
        List<TemplateRangeDTO> templateRangeDTOS = new LinkedList<>();

        for (Template template : templates) {
            if (Objects.equals(templateId, template.getTemplateId())) {
                continue;
            }
            TemplateRangeDTO templateRangeDTO = new TemplateRangeDTO();
            templateRangeDTO.setTemplateId(template.getTemplateId());
            templateRangeDTO.setDepartmentIds(template.getDepartmentId());
            templateRangeDTO.setContactIdRange(template.getRangeSpecific());
            templateRangeDTO.setCompanyInfoIdRange(template.getCompanyInfoIdRange());

            templateRangeDTOS.add(templateRangeDTO);
        }
        return templateRangeDTOS;
    }

    private void setTimesLimitCondition(Map<Integer, Integer> timesMap, List<TemplateDTO> templates, Map<Integer, Integer> templateTimeMap) {
        for (TemplateDTO template : templates) {
            if (template.getDefaultType() == Template.APPEND_SIGN
                    || template.getDefaultType() == Template.COMPENSATORY_LEAVE) {
                template.setTimesLeftThisMonth(0);
                if (template.getMaxTimePermonth() != 0) {
                    Integer times = templateTimeMap.get(template.getAncestorId());
                    times = (times == null ? 0 : times);
                    template.setTimesLeftThisMonth((template.getMaxTimePermonth() - times));
                }
            } else {
                template.setTimesLeftThisMonth(0);
                if (template.getMaxTimePermonth() != 0) {
                    Integer times = timesMap.get(template.getDefaultType());
                    times = (times == null ? 0 : times);
                    template.setTimesLeftThisMonth((template.getMaxTimePermonth() - times));
                }
            }
        }
    }

    private List<Template> copyToTemplates(List<TemplateDTO> templateDTOs) {
        List<Template> templates = new ArrayList<>(templateDTOs.size());

        for (TemplateDTO templateDTO : templateDTOs) {
            Template template = new Template();

            template.setTemplateId(templateDTO.getTemplateId());
            template.setTemplateName(templateDTO.getTemplateName());
            template.setTemplateColor(templateDTO.getTemplateColor());
            template.setVersion(templateDTO.getVersion());
            template.setDefaultType(templateDTO.getDefaultType());
            template.setAmountTop(templateDTO.getAmountTop());
            template.setDepartmentId(templateDTO.getDepartmentIds());
            template.setAncestorId(templateDTO.getAncestorId());
            template.setMaxTimePermonth(templateDTO.getMaxTimePermonth());
            template.setContentTimeLimit(templateDTO.getContentTimeLimit());
            template.setIsMaxTime(templateDTO.getIsMaxTime());
            template.setTimesLeftThisMonth(templateDTO.getTimesLeftThisMonth());
            template.setRangeSpecific(templateDTO.getSpecificRange());
            template.setCompanyInfoIdRange(templateDTO.getCompanyInfoIdRange());

            templates.add(template);
        }

        return templates;
    }


    @Override
    public List<Template> getMyCompanysTemplateList(User user) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            SelectTemplateDao selectTemplateDao = DaoFactory.getSelectTemplateDao(connection);
            AppendSignDao appendSignDao = new AppendSignDaoImpl(connection);
            LeaveDao leaveDao = new LeaveDaoImpl(connection);
            RequestDao requestDao = new RequestDaoImpl(connection);

            List<TemplateDTO> companyTemplates = selectTemplateDao.selectCompanyTemplates(user.getCompanyId());
            if (Utils.isEmpty(companyTemplates)) {
                return null;
            }
            Map<Integer, Integer> timesMap = selectTemplateDao.getUsedTimesByMonth(user.getCompanyInfoId(), DateUtils.getCurrentMonth());

            List<TemplateDTO> filteredTemplates = TemplateUtils.filterTemplatesByUser(user, companyTemplates);
            // 补卡次数集合
            Map<Integer, Integer> checkInMap = appendSignDao.selectUserAppendSignsTimesMapByMonth(user.getCompanyId(), user.getCompanyInfoId(), DateUtils.getCurrentMonth());
            // 请假次数集合
            Map<Integer, Integer> leaveMap = leaveDao.selectUserLeaveTimesMapByMonth(user.getCompanyId(), user.getCompanyInfoId(), DateUtils.getCurrentMonth());

            Map<Integer, Integer> templateTimeMap = new HashMap<>();
            templateTimeMap.putAll(checkInMap);
            templateTimeMap.putAll(leaveMap);

            setTimesLimitCondition(timesMap, filteredTemplates, templateTimeMap);

            List<Template> templates = copyToTemplates(filteredTemplates);
            try {
                List<Integer> ancestorIds = requestDao.selectUsualTemplateAncestorIds(user.getCompanyId(), user.getCompanyInfoId());

                if (Utils.isNotEmpty(ancestorIds)) {
                    List<Integer> ids = new ArrayList<>();
                    for (Integer ancestorId : ancestorIds) {
                        if (ids.contains(ancestorId)) {
                            continue;
                        }
                        if (ids.size() == 2) {
                            break;
                        }
                        ids.add(ancestorId);
                    }

                    List<Integer> list = ListHelper.sortByOccurrenceNumber(ancestorIds);
                    for (Integer id : list) {
                        if (ids.contains(id)) {
                            continue;
                        }
                        if (ids.size() == 5) {
                            break;
                        }
                        ids.add(id);
                    }
                    for (int i = 0; i < ids.size(); i++) {
                        for (Template template : templates) {
                            if (Objects.equals(ids.get(i), template.getAncestorId())) {
                                template.setUsualSort(i + 1);
                                break;
                            }
                        }
                    }
                }
            } catch (Throwable e) {
                logger.error(e.getMessage(), e);
            }

            return templates;
        } catch (Throwable e) {
            logger.error(e.getMessage(), e);
            throw ErrorUtils.throwError(e);
        } finally {
            DBUtils.release(connection);
        }
    }

    @Override
    public void initMyCompanysTemplateList(User user, List<Template> defaultTemplates) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            TemplateDao templateDao = new TemplateDaoImpl(connection);

            templateDao.initMyCompanyTemplateList(user.getCompanyId(), defaultTemplates);
        } catch (Throwable e) {
            throw ErrorUtils.throwError(e, logger);
        } finally {
            DBUtils.release(connection);
        }
    }

    @Override
    public List<Template> getDefaultTemplateToInit(User user) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            TemplateDao templateDao = new TemplateDaoImpl(connection);
            return templateDao.getDefaultTemplateToInit();
        } catch (Throwable e) {
            throw ErrorUtils.throwError(e, logger);
        } finally {
            DBUtils.release(connection);
        }
    }

    @Override
    public List<Template> getAllOfMyCompanyTemplate(User user) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            TemplateDao templateDao = new TemplateDaoImpl(connection);
            //并发会造成什么情况？待观察
            return templateDao.getAllOfMyCompanyTemplate(user);
        } catch (Throwable e) {
            throw ErrorUtils.throwError(e, logger);
        } finally {
            DBUtils.release(connection);
        }
    }

    @Override
    public List<Template> getTemplateFitToWholeCompanyRangeList(User user) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            TemplateDao templateDao = new TemplateDaoImpl(connection);

            //并发会造成什么情况？待观察
            return templateDao.getTemplateFitToWholeCompanyRangeList(user);
        } catch (Throwable e) {
            throw ErrorUtils.throwError(e, logger);
        } finally {
            DBUtils.release(connection);
        }
    }

    @Override
    public List<TemplateInfoDTO> getTemplateCount(Integer companyId) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            SelectTemplateDao selectTemplateDao = new SelectTemplateDaoImpl(connection);

            List<TemplateInfoDTO> templateUsedTimes = selectTemplateDao.selectTemplateUsedTimes(companyId);

            Map<Integer, List<TemplateRangeDTO>> templateTypeMap = selectTemplateDao.getTemplatesGroupByType(companyId);

            setTemplateUserRange(templateUsedTimes, templateTypeMap, companyId);

            return templateUsedTimes;
        } catch (Throwable e) {
            logger.error(e.getMessage(), e);
            throw ErrorUtils.throwError(e);
        } finally {
            DBUtils.release(connection);
        }
    }

    private void setTemplateUserRange(List<TemplateInfoDTO> templateInfoDTOs, Map<Integer, List<TemplateRangeDTO>> templateTypeMap, Integer companyId) throws Throwable {
        UserServicePrx userService = ServantUtils.getObject(UserServicePrx.class);

        // 获取所有在职的员工集合
        List<User> allNormalUsers = userService.getAllNormalUserListWithAdmin(companyId);
        List<User> allUsers = UserUtils.uniqueUsersByCompanyInfoId(allNormalUsers);
        List<Integer> allUserCompanyInfoIds = ListHelper.getCompanyInfoIdList(allUsers);

        for (TemplateInfoDTO templateInfoDTO : templateInfoDTOs) {
            // 预先设置该审批类型不存在适用范围为全公司的模板
            templateInfoDTO.setExistCompanyRangeTemplate(0);

            List<TemplateRangeDTO> templateRangeDTOs = templateTypeMap.get(templateInfoDTO.getDefaultType());
            if (isCompanyRange(templateRangeDTOs)) {
                templateInfoDTO.setExistCompanyRangeTemplate(1);
            }

            if (templateInfoDTO.getExistCompanyRangeTemplate().equals(0)) {
                logger.info("模板类型:{} ", templateInfoDTO.getDefaultType());
                List<Integer> companyInfoIdRanges = getCompanyInfoIdRanges(companyId, userService, templateRangeDTOs);
                logger.info("公司范围:{}", allUserCompanyInfoIds);
                logger.info("模板范围:{}", companyInfoIdRanges);

                if (ListHelper.isSubList(allUserCompanyInfoIds, companyInfoIdRanges)) {
                    templateInfoDTO.setExistCompanyRangeTemplate(1);
                }
            }
        }
    }

    private boolean isCompanyRange(List<TemplateRangeDTO> templateRangeDTOs) {
        for (TemplateRangeDTO templateRangeDTO : templateRangeDTOs) {
            if (ApprovalUtils.isAllCompanyRange(templateRangeDTO.getDepartmentIds())) {
                return true;
            }
        }
        return false;
    }

    private List<Integer> getCompanyInfoIdRanges(Integer companyId, UserServicePrx userService, List<TemplateRangeDTO> templateRangeDTOs) throws Throwable {
        List<Integer> companyInfoIdRanges = new ArrayList<>();
        List<String> deptIds = new ArrayList<>();
        List<String> companyInfoIds = new ArrayList<>();

        for (TemplateRangeDTO templateRangeDTO : templateRangeDTOs) {
            // 指定部门或指定人
            if (ApprovalUtils.isSpecifiedDepts(templateRangeDTO.getDepartmentIds())) {
                deptIds.addAll(Arrays.asList(templateRangeDTO.getDepartmentIds().split(",")));
            }
            // 当部门没有人,又没有指定人的时候,companyInfoIdRange会为null
            if (StringUtils.isNotEmpty(templateRangeDTO.getCompanyInfoIdRange())) {
                companyInfoIds.addAll(Arrays.asList(templateRangeDTO.getCompanyInfoIdRange().split(",")));
            }
        }

        if (ListHelper.isNotNullEmpty(deptIds)) {
            List<User> deptUsers = userService.getAllUserListByDepartmentIds(companyId, ListHelper.list2string(deptIds));
            if (ListHelper.isNotNullEmpty(deptUsers)) {
                for (User user : deptUsers) {
                    if (!companyInfoIdRanges.contains(user.getCompanyInfoId())) {
                        companyInfoIdRanges.add(user.getCompanyInfoId());
                    }
                }
            }
        }

        if (ListHelper.isNotNullEmpty(companyInfoIds)) {
            for (String companyInfoId : companyInfoIds) {
                if (!companyInfoIdRanges.contains(Integer.valueOf(companyInfoId))) {
                    companyInfoIdRanges.add(Integer.valueOf(companyInfoId));
                }
            }
        }

        return companyInfoIdRanges;
    }

    @Override
    public Template getTemplateDetail(Template dto) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            TemplateDao templateDao = new TemplateDaoImpl(connection);

            Template template = templateDao.selectTemplateDetailById(dto.getTemplateId());
            if (template == null) {
                throw new RpcServerLogicalException(1, "该模板已被修改，请重新加载");
            }
            //如果该模板的审批流程是~~~条件比较
            if ("Condition".equals(template.getRequestFlow())) {
                User user = new User();
                user.setCompanyId(template.getCompanyId());
                List<ConditionFlow> conditionFlows = templateDao.selectConditionFlowList(template.getTemplateId());
                template.setConditionFlow(conditionFlows);
            }
            try {
                if (StringUtils.isNotEmpty(template.getDepartmentId()) && !"0".equals(template.getDepartmentId())) {
                    UserServicePrx userService = ServantUtils.getObject(UserServicePrx.class);
                    List<User> userList = userService.getUserListByDepartmentIds(template.getCompanyId(), template.getDepartmentId());
                    Set<Integer> contactIds = new HashSet<>(), companyInfoIds = new HashSet<>();
                    for (User user : userList) {
                        contactIds.add(user.getContactId());
                        companyInfoIds.add(user.getCompanyInfoId());
                    }
                    contactIds.addAll(ListHelper.string2IntegerList(template.getRangeSpecific()));
                    companyInfoIds.addAll(ListHelper.string2IntegerList(template.getCompanyInfoIdRange()));

                    template.setRangeSpecific(ListHelper.collectionToString(contactIds));
                    template.setCompanyInfoIdRange(ListHelper.collectionToString(companyInfoIds));
                }
            } catch (Throwable throwable) {
                logger.error(throwable.getMessage(), throwable);
                EmailUtils.sendMail("调整适用范围出错", throwable);
            }
            //离职员工过滤
            return resignedFilter(template);
        } catch (Throwable e) {
            throw ErrorUtils.throwError(e, logger);
        } finally {
            DBUtils.release(connection);
        }
    }

    @Override
    public List<StaticData> getTemplateCurrentObjectUsedLastMonth(Template t, User comUser) throws Throwable {
        if (t == null) {
            throw new RpcServerLogicalException(ApprovalRespCodeDesc.MISS_TEMPLATE);
        }
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            TemplateDao templateDao = new TemplateDaoImpl(connection);
            UserServicePrx userService = ServantUtils.getObject(UserServicePrx.class);
            StaticDao staticDao = new StaticDaoImpl(connection);

            List<Template> list = templateDao.getTemplateFamilyByTemplates(t, comUser);
            List<Template> matchedTemplates = new LinkedList<>();
            for (Template template : list) {
                List<TemplateComponent> tcl = JSONArray.parseArray(template.getTemplateComponent(), TemplateComponent.class);
                if (t.getSiftingBy() != null && !"".equals(t.getSiftingBy().trim())) {
                    //根据名字来
                    for (TemplateComponent tc : tcl) {
                        if (tc.getName().equals(t.getSiftingBy())) {
                            if (tc.getType() != 3 && tc.getType() != 13) {
                                throw new RpcServerLogicalException(1, "非数字段");
                            }
                            template.setCurrentNum(tc.getNum());
                            break;
                        }
                    }
                } else {
                    //根据数字来
                    for (TemplateComponent tc : tcl) {
                        if (Objects.equals(tc.getNum(), t.getDataNum())) {
                            template.setCurrentNum(tc.getNum());
                            break;
                        }
                    }
                }
                if (Utils.isNotNull(template.getCurrentNum()) && template.getCurrentNum() != 0) {
                    matchedTemplates.add(template);
                }
            }
            List<StaticData> sds = new ArrayList<>();
            if (matchedTemplates.size() > 0) {
                //获得这个模板上个月使用的次数（这个num不为空），然后计算总值
                sds = staticDao.getCurrentObjectNotNullTimesOfCurrentTemplate(t, matchedTemplates);
                if (sds.isEmpty()) {        // 如果没有被使用过,直接返回
                    return sds;
                }

                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < sds.size(); i++) {
                    sb.append(sds.get(i).getContactId());
                    if (sds.size() - i > 1) {
                        sb.append(",");
                    }
                }
                List<User> users = userService.getUserListByContactIds(sb.toString());
                Map<Integer, User> idToUser = new HashMap<>();
                for (User user : users) {
                    idToUser.put(user.getContactId(), user);
                }

                for (int i = 0; i < sds.size(); i++) {
                    StaticData sd = sds.get(i);
                    if (idToUser.containsKey(sd.getContactId())) {
                        sd.setCompanyInfoId(idToUser.get(sd.getContactId()).getCompanyInfoId());
                    }
                    sds.set(i, sd);
                }
                //合并多身份
                if (Objects.equals(t.getIsMergeMultiId(), 1)) {
                    Map<Integer, StaticData> map = new HashMap<>();
                    for (StaticData sd : sds) {
                        if (map.containsKey(sd.getCompanyInfoId())) {
                            sd.setSum(sd.getSum().add(map.get(sd.getCompanyInfoId()).getSum()).setScale(2, RoundingMode.HALF_UP));
                            sd.setContactId(sd.getCompanyInfoId());
                            map.put(sd.getCompanyInfoId(), sd);
                        } else {
                            map.put(sd.getCompanyInfoId(), sd);
                        }
                    }
                    sds = new ArrayList<>();
                    for (Map.Entry<Integer, StaticData> e : map.entrySet()) {
                        sds.add(e.getValue());
                    }
                }
            }
            return sds;
        } catch (Throwable e) {
            throw ErrorUtils.throwError(e, logger);
        } finally {
            DBUtils.release(connection);
        }
    }

    private Template resignedFilter(Template template) throws Throwable {
        //过滤审批流离职员工
        StringBuilder sb = new StringBuilder();
        String requestFlow = template.getRequestFlow();
        logger.info(Formatter.aformat("老审批流为 ?", requestFlow));

        if (requestFlow.contains("SP") || requestFlow.contains("DM")) {
            return template;
        }

        if (requestFlow.contains("&&") || requestFlow.contains("||")) {
            // TODO 后续处理
            return template;
        }

        UserServicePrx userService = ServantUtils.getObject(UserServicePrx.class);

        if (!"default".equals(requestFlow) && !"Alternative".equals(requestFlow) && !"Condition".equals(requestFlow)) {
            List<Integer> requestFlowOriginNumberList = ListHelper.stringToIntegerArrayList(requestFlow);
            List<String> requestFlowOriginList = ListHelper.stringToStringArrayList(requestFlow);
            List<Integer> requestFlowOnDutyNumberList = new ArrayList<>();
            if (requestFlowOriginNumberList.size() > 0) {
                for (int i = 0; i < requestFlowOriginNumberList.size(); i++) {
                    sb.append(requestFlowOriginNumberList.get(i));
                    if (requestFlowOriginNumberList.size() - i > 1) {
                        sb.append(",");
                    }
                }
                List<User> userOnDuty = userService.getUserListByContactIds(sb.toString());  // 会过滤离职身份
                for (User anUserOnDuty : userOnDuty) {
                    requestFlowOnDutyNumberList.add(anUserOnDuty.getContactId());
                }
                if (requestFlowOriginNumberList.size() != requestFlowOnDutyNumberList.size()) {
                    logger.info("模板里有审批流出现离职状况，开始去除");
                    List<Integer> diff = ListHelper.getListDifferent(requestFlowOriginNumberList, requestFlowOnDutyNumberList);
                    for (Integer aDiff : diff) {
                        logger.info(Formatter.aformat("? 已离职", aDiff));
                        requestFlowOriginList.remove(String.valueOf(aDiff));
                    }
                    StringBuilder flowNew = new StringBuilder();
                    for (int i = 0; i < requestFlowOriginList.size(); i++) {
                        flowNew.append(requestFlowOriginList.get(i));
                        if (requestFlowOriginList.size() - i > 1) {
                            flowNew.append(",");
                        }
                    }
                    logger.info(Formatter.aformat("新审批流为 ?", flowNew.toString()));
                    template.setRequestFlow(flowNew.toString());
                }
            }
        }
        return template;
    }

    @Override
    public Template getDetaultTemplateDetail(Integer templateId) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            TemplateDao templateDao = new TemplateDaoImpl(connection);
            return templateDao.getDefaultTemplateDetail(templateId);
        } catch (Throwable e) {
            throw ErrorUtils.throwError(e, logger);
        } finally {
            DBUtils.release(connection);
        }
    }


    private void setTemplateAncestorInfo(Template template, User user, TemplateDao templateDao) throws SQLException {
        // 是否修改模板
        if (template.getTemplateId() != 0) {
            // 获取被修改模板的模板
            Template ancestor = templateDao.getAncestorTemplateSimpleInfo(template.getTemplateId(), user.getCompanyId());
            if (Objects.equals(ancestor.getAncestorId(), 0)) {
                throw new RpcServerLogicalException(ApprovalRespCodeDesc.MISS_TEMPLATE);
            }

            // 重复提交,提示用户提交成功,不再点击
            if (Utils.isNull(ancestor.getStatus()) || ancestor.getStatus() == 0) {
                throw new RpcServerLogicalException(1, "提交成功");
            }

            templateDao.disableTemplate(template.getTemplateId(), user.getCompanyId());

            template.setVersion(ancestor.getVersion() + 1);
            template.setAncestorId(ancestor.getAncestorId());

        } else {
            // 新建模板
            template.setVersion(1);
            template.setAncestorId(template.getTemplateInsertId());
        }
    }

    @Override
    public void settingNewOriginTemplate(Template template, User user, int generation) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            TemplateDao templateDao = new TemplateDaoImpl(connection);
            TemplateFolderDao folderDao = new TemplateFolderDaoImpl(connection);
            ModifyDao modifyDao = new ModifyDaoImpl(connection);
            GlobalSettingDao globalSettingDao = new GlobalSettingDaoImpl(connection);

            if (Objects.equals(template.getIsFinancial(), 1) && StringUtils.isEmpty(template.getFinancialFlow())) {
                GlobalSetting globalSetting = globalSettingDao.selectGlobalSetting(user.getCompanyId());
                if (StringUtils.isEmpty(globalSetting.getFinancialFlow())) {
                    throw new RpcServerLogicalException(1, "请设置财务审批流");
                }
            }

            DBUtils.begin(connection);

            setTemplateAncestorInfo(template, user, templateDao);

            //设置审批流程
            String flowType = RequestFlowType.getFlowType(template.getRequestFlow());
            switch (flowType) {
                case RequestFlowType.CONDITION:
                    checkConditionFlow(template.getConditionFlow());
                    templateDao.insertConditionRequestFlow(template, user);
                    ApprovalAuthUtils.addAuthJudgerInConditionFlow(template.getConditionFlow(), user);
                    break;
                case RequestFlowType.SP_DEFINE:
                case RequestFlowType.SP_DM_DEFINE:
                case RequestFlowType.ALL_NUMBER:
                    ApprovalAuthUtils.addAuthForJudger(template.getRequestFlow(), user);
                    break;
                default:
                    break;
            }
            AdjustUtils.adjustTemplate(template);

            List<TemplateFolder> folderToUpdate = new ArrayList<>();
            List<ApprovalModify> modifies = new ArrayList<>();
            if (Utils.isNotNull(template.getGroupId()) && template.getGroupId() > 0) {
                List<TemplateFolder> templateFolders = folderDao.selectTemplateFolders(user.getCompanyId());
                String oldName = "", newName = "";
                for (TemplateFolder folder : templateFolders) {
                    if (Objects.equals(folder.getId(), template.getGroupId())) {
                        folder.addTemplate(template.getAncestorId());
                        folderToUpdate.add(folder);
                        newName = folder.getName();
                    } else if (folder.includeTemplate(template)) {
                        folder.removeTemplate(template.getAncestorId());
                        folderToUpdate.add(folder);
                        oldName = folder.getName();
                    }
                }
                ApprovalModify modify = new ApprovalModify();
                modify.setCompanyId(user.getCompanyId());
                modify.setCompanyInfoId(user.getCompanyInfoId());
                modify.setTitle(String.format("%s 修改模板 「%s」 分组", user.getContactName(), template.getTemplateName()));
                modify.setDetail(String.format("%s → %s", oldName, newName));
                modify.setTemplateId(template.getTemplateId());
                modify.setTemplateAncestorId(template.getAncestorId());
                modifies.add(modify);
            }

            templateDao.insertOriginTemplate(template, user, generation);
            if (Utils.isNotEmpty(folderToUpdate)) {
                folderDao.updateBatchTemplateFolder(folderToUpdate);
            }
            if (Utils.isNotEmpty(modifies)) {
                modifyDao.insertBatchModifies(modifies);
            }
            DBUtils.commit(connection);

            template.setUser(user);
            if (template.getTemplateId() > 0) {
                template.setModifyType("update");
            } else {
                template.setModifyType("add");
            }
            MQUtils.sendMessage(Constants.MQ_APPROVAL_TOPIC, Constants.MQ_TAG_APPROVAL_MODIFY, template);
        } catch (Throwable e) {
            DBUtils.rollback(connection);
            logger.error(e.getMessage(), e);
            throw ErrorUtils.throwError(e);
        } finally {
            DBUtils.release(connection);
        }
    }


    private void checkConditionFlow(List<ConditionFlow> list) {
        if (ListHelper.isNullEmpty(list)) {
            throw new RpcServerLogicalException(1, "条件规则不能为空");
        }

        // 上次条件的最大值
        BigDecimal lastLargestFactor = BigDecimal.ZERO;
        for (int i = 0; i < list.size(); i++) {
            ConditionFlow conditionFlow = list.get(i);

            BigDecimal smallerFactor = conditionFlow.getSmallerFactor();
            BigDecimal greaterFactor = conditionFlow.getGreaterFactor();
            String relaComponentNum = conditionFlow.getRelaComponentNum();

            if (StringUtils.isEmpty(relaComponentNum)) {
                throw new RpcServerLogicalException(1, "请设置关联组件");
            }

            if (StringUtils.isEmpty(conditionFlow.getRequestFlow())) {
                throw new RpcServerLogicalException(1, "请设置审批流");
            }

            // 条件计算类型：1：比较，2：在某某范围内
            if (conditionFlow.getConditionCalculationType() == ConditionCalculationType.TO_COMPARE) {
                if (Utils.isNull(smallerFactor)) {
                    throw new RpcServerLogicalException(1, "请设置初始条件");
                }

                // 第一个条件
                if (i == 0) {
                    firstCheck(smallerFactor, greaterFactor);
                    lastLargestFactor = greaterFactor;
                }

                // 最后一个条件
                if (i == list.size() - 1) {
                    lastCheck(smallerFactor, lastLargestFactor);
                }

                // 中间条件
                if (i > 0 && i < list.size() - 1) {
                    otherCheck(smallerFactor, greaterFactor, lastLargestFactor);
                    lastLargestFactor = greaterFactor;
                }
            } else if (conditionFlow.getConditionCalculationType() == ConditionCalculationType.RADIO_BUTTON) {
                if (StringUtils.isEmpty(conditionFlow.getChooseItems())) {
                    throw new RpcServerLogicalException(1, "请设置条件选项");
                }
            }
        }
    }

    private void firstCheck(BigDecimal smallerFactor, BigDecimal greaterFactor) {
        if (smallerFactor.compareTo(BigDecimal.ZERO) < 0) {
            throw new RpcServerLogicalException(1, "请设置条件或初始条件应为0");
        }

        if (Utils.isNull(greaterFactor)) {
            throw new RpcServerLogicalException(1, "请设置右边条件");
        }

        if (smallerFactor.compareTo(greaterFactor) >= 0) {
            throw new RpcServerLogicalException(1, "第一条件最大值应大于最小值");
        }
    }

    private void lastCheck(BigDecimal smallerFc, BigDecimal greaterFactor) {
        if (smallerFc.compareTo(greaterFactor) != 0) {
            throw new RpcServerLogicalException(1, "下一条件的最小值必须为上一条件的最大值");
        }
    }

    private void otherCheck(BigDecimal smallerFactor, BigDecimal greaterFactor, BigDecimal lastLargestFactor) {/**/
        if (smallerFactor.compareTo(lastLargestFactor) != 0) {
            throw new RpcServerLogicalException(1, "下一条件的最小值必须为上一条件的最大值");
        }
        if (smallerFactor.compareTo(greaterFactor) >= 0) {
            throw new RpcServerLogicalException(1, "右边条件最大值应大于左边最小值");
        }
    }

    @Override
    public void deleteTemplate(Template template, User user) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            TemplateDao templateDao = new TemplateDaoImpl(connection);
            TemplateFolderDao folderDao = new TemplateFolderDaoImpl(connection);

            template = templateDao.getTemplateDetailWithoutVersion(template);

            List<TemplateFolder> folders = folderDao.selectTemplateFolders(user.getCompanyId());
            Template finalTemplate = template;
            List<TemplateFolder> folderToUpdate = folders.stream().filter(templateFolder -> templateFolder.includeTemplate(finalTemplate)).collect(Collectors.toList());

            DBUtils.begin(connection);
            templateDao.deleteTemplate(template, user);
            if (Utils.isNotEmpty(folderToUpdate)) {
                for (TemplateFolder folder : folderToUpdate) {
                    folder.removeTemplate(template.getAncestorId());
                }
                folderDao.updateBatchTemplateFolder(folderToUpdate);
            }

            DBUtils.commit(connection);
            template.setUser(user);
            template.setModifyType("delete");
            MQUtils.sendMessage(Constants.MQ_APPROVAL_TOPIC, Constants.MQ_TAG_APPROVAL_MODIFY, template);
        } catch (Throwable e) {
            throw ErrorUtils.throwError(e, logger);
        } finally {
            DBUtils.release(connection);
        }
    }

    @Override
    public List<StaticData> getStaticData(List<Integer> list) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            StaticDao staticDao = new StaticDaoImpl(connection);
            UserServicePrx userService = ServantUtils.getObject(UserServicePrx.class);

            List<StaticData> staticDatas = new ArrayList<>();

            for (Integer contactId : list) {
                StaticData staticdata = new StaticData();
                staticdata.setContactId(contactId);

                List<RequestLite> requestLiteList = new ArrayList<>();
                staticdata.setList(requestLiteList);
                // 审批分为：发起审批，审批审批，评论审批，归档审批

                // 获取10条该用户申请的审批
                staticdata = staticDao.getLatest10RequestBySelf(staticdata);
                //审批审批列表
                User user = userService.getUserByContactId(contactId);

                Request request = new Request();
                request.setApplicant(user.getContactId());
                request.setPage(1);
                request.setDataNum(10);

                List<Request> otherList = staticDao.selectLast10UserApprovedRequest(user.getCompanyId(), user.getCompanyInfoId());

                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                // 审批审批列表
                List<RequestLite> liteList = new ArrayList<>();
                for (Request rt : otherList) {
                    RequestLite rl = new RequestLite();
                    rl.setRequestName("审批");
                    rl.setTime(new Timestamp(sdf.parse(rt.getCheckedTime()).getTime()));
                    rl.setTimeStr(sdf.format(new Date(rl.getTime().getTime())));
                    rl.setContent("进行审批-" + rt.getRequestName());
                    rl.setApplicant(rt.getApplicant());
                    rl.setRequestDkey(rt.getRequestDkey());
                    liteList.add(rl);
                }

                logger.info("requestInfo:{}", liteList.toString());

                List<RequestLite> rtList = staticdata.getList();
                rtList.addAll(liteList);
                staticdata.setList(rtList);
				/*
				  评论审批
				 */
                staticdata = staticDao.getLatest10CommentRequestBySelf(staticdata);
				/*
				  归档审批
				 */
                staticdata = staticDao.getLatest10FiledRequestBySelf(staticdata);
                getLatest10(staticdata);

                StringBuilder sb = new StringBuilder();
                List<RequestLite> sdList = staticdata.getList();
                for (int i = 0; i < sdList.size(); i++) {
                    RequestLite r = sdList.get(i);
                    sb.append(r.getApplicant());
                    if (sdList.size() - i > 1) {
                        sb.append(",");
                    }
                }
                if (sb.length() > 0 && !"".equals(sb.toString())) {
                    if (sb.toString().endsWith(",")) {
                        sb.deleteCharAt(sb.length() - 1);
                    }

                    List<User> people = userService.getUserListByContactIds(sb.toString());
                    Map<Integer, String> idName = new HashMap<>();
                    for (User aPeople : people) {
                        idName.put(aPeople.getContactId(), aPeople.getContactName());
                    }
                    for (int i = 0; i < sdList.size(); i++) {
                        RequestLite r = sdList.get(i);
                        if (idName.containsKey(r.getApplicant())) {
                            r.setApplicantName(idName.get(r.getApplicant()));
                            sdList.set(i, r);
                        }
                    }
                }
                logger.info("最终数据:{}", sdList);
                staticdata.setList(sdList);
                staticDatas.add(staticdata);
            }
            return staticDatas;
        } catch (Throwable e) {
            logger.error(e.getMessage(), e);
            throw ErrorUtils.throwError(e);
        } finally {
            DBUtils.release(connection);
        }
    }

    private void getLatest10(StaticData staticdata) {
        List<RequestLite> rtList = staticdata.getList();
        rtList.sort((o1, o2) -> Long.compare(o2.getTime().getTime(), o1.getTime().getTime()));
        List<RequestLite> one = rtList.subList(0, Math.min(rtList.size(), 10));
        List<RequestLite> two = new ArrayList<>(one);
        one.clear();
        staticdata.setList(two);
    }

    @Override
    public List<UsualUser> GetMyUsualRelaPeople(User user) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            List<UsualUser> result = new ArrayList<>();
            ParticipantDao participantDao = new ParticipantDaoImpl(connection);
            List<Integer> contactIds = participantDao.selectUserNearlyParticipant(user.getCompanyInfoId());
            if (Utils.isEmpty(contactIds)) {
                return result;
            }
            List<Integer> ids = new ArrayList<>();
            for (Integer id : contactIds) {
                if (!ids.contains(id)) {
                    ids.add(id);
                }
                if (ids.size() == 3) {
                    // 三个最近添加的
                    break;
                }
            }
            contactIds = ListHelper.sortByOccurrenceNumber(contactIds);
            for (Integer contactId : contactIds) {
                if (!ids.contains(contactId)) {
                    ids.add(contactId);
                }
                if (ids.size() == 8) {
                    // 五个最频繁使用的
                    break;
                }
            }
            UserServicePrx userServicePrx = ServantUtils.getObject(UserServicePrx.class);
            List<User> userList = userServicePrx.getUserBaseInfoListByContactIds(user.getCompanyId(), Utils.collection2string(ids));
            userList = userList.stream().filter(o -> !Objects.equals(o.getQuit(), true)).collect(Collectors.toList());
            if (Utils.isEmpty(userList)) {
                logger.info("已全部离职");
                return result;
            }
            userList.sort(Comparator.comparingInt(o -> ids.indexOf(o.getContactId())));
            for (User u : userList) {
                UsualUser usualUser = new UsualUser();
                usualUser.setContactId(u.getContactId());
                result.add(usualUser);
            }
            return result;
        } catch (Throwable e) {
            throw ErrorUtils.throwError(e, logger);
        } finally {
            DBUtils.release(connection);
        }
    }

    @Override
    public List<Template> getSomeonesApprovalCostPeriod(Request query, User user) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            TemplateDao templateDao = new TemplateDaoImpl(connection);
            ComponentDao componentDao = new ComponentImpl(connection);

            List<Template> result = new ArrayList<>();
            //获得关联成本分析的所有模板
            List<Template> templates = templateDao.selectCostAnalysisTemplates(user);
            if (Utils.isEmpty(templates)) {
                return result;
            }
            // 获得这个人的这些模板的审批，在一定范围内
            List<Request> requests = templateDao.getRequestByTemplates(templates, query);
            if (Utils.isEmpty(requests)) {
                return result;
            }
            // 创建现有模板ID和祖先ID的关系map（为了后面设置返回数据用）
            Map<Integer, Integer> ancestorIdMap = new HashMap<>();
            Map<Integer, Template> templateMap = new HashMap<>();
            for (Template template : templates) {
                ancestorIdMap.put(template.getAncestorId(), template.getTemplateId());
                templateMap.put(template.getTemplateId(), template);
            }

            //step.3 获得审批内容
            if (Utils.isEmpty(requests)) {
                return result;
            }

            List<Integer> requestIds = RequestUtils.getRequestIds(requests);
            Map<Integer, List<TemplateComponent>> componentMap = componentDao.selectComponentMapByRequestIds(Utils.list2string(requestIds));

            Map<Integer, BigDecimal> templateCosts = new HashMap<>();
            for (Request request : requests) {
                Template template = templateMap.get(request.getTemplateId());
                BigDecimal cost = calculateCost(request, componentMap.get(request.getRequestDkey()));
                if (templateCosts.containsKey(template.getAncestorId())) {
                    templateCosts.put(template.getAncestorId(), templateCosts.get(template.getAncestorId()).add(cost));
                } else {
                    templateCosts.put(template.getAncestorId(), cost);
                }
            }

            for (Map.Entry<Integer, BigDecimal> entry : templateCosts.entrySet()) {
                if (ancestorIdMap.containsKey(entry.getKey())) {
                    Integer templateId = ancestorIdMap.get(entry.getKey());
                    Template template = templateMap.get(templateId);
                    template.setTotalCosts(entry.getValue().setScale(2, RoundingMode.HALF_UP));
                    result.add(template);
                }
            }

            return result;
        } catch (Throwable e) {
            throw ErrorUtils.throwError(e, logger);
        } finally {
            DBUtils.release(connection);
        }
    }

    private BigDecimal calculateCost(Request req, List<TemplateComponent> components) {
        BigDecimal cost = new BigDecimal(0);
        if (Utils.isEmpty(components)) {
            return cost;
        }
        if (req.getDefaultType() == Template.EXPENSES) {
            //报销类
            TemplateComponent component = ComponentUtils.getComponentByNumber(components, 2);
            if (Utils.isNull(component) || StringUtils.isBlank(component.getValue())) {
                return cost;
            }
            String value = component.getValue();
            if (ValidateUtil.isDouble(value)) {
                cost = new BigDecimal(value);
            } else {
                List<String> subValues = JSONObject.parseArray(value, String.class);
                for (String subValue : subValues) {
                    cost = cost.add(new BigDecimal(subValue));
                }
            }

        }
        if (req.getDefaultType() == Template.OTHER) {
            //自定义类
            List<TemplateComponent> moneyComponents = ComponentUtils.getComponentByType(components, ContentType.MONEY);
            for (TemplateComponent tc : moneyComponents) {
                if (!ValidateUtil.isDouble(tc.getValue())) {
                    continue;
                }
                //step.5 放进map里
                cost = new BigDecimal(tc.getValue());
            }
        }
        return cost;
    }

    @Override
    public List<CostPeriod> getOnesApprovalCostPeriod(Request query) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            TemplateDao templateDao = new TemplateDaoImpl(connection);
            ComponentDao componentDao = new ComponentImpl(connection);

            List<CostPeriod> result = new ArrayList<>();

            // 获得关联成本分析的所有模板
            List<Template> templates = templateDao.selectCostAnalysisTemplates(query);
            if (Utils.isEmpty(templates)) {
                return result;
            }
            // 获得这个人的这些模板的审批，在一定范围内
            List<Request> requests = templateDao.getRequestByTemplatesWithSearchRangeAndCurrentMonths(templates, query);
            if (Utils.isEmpty(requests)) {
                return result;
            }
            // 创建现有模板ID和祖先ID的关系map（为了后面设置返回数据用）
            Map<Integer, Integer> ancestorIdMap = new HashMap<>();
            Map<Integer, Template> templateMap = new HashMap<>();
            for (Template template : templates) {
                ancestorIdMap.put(template.getAncestorId(), template.getTemplateId());
                templateMap.put(template.getTemplateId(), template);
            }
            List<Integer> requestIds = RequestUtils.getRequestIds(requests);
            Map<Integer, List<TemplateComponent>> componentMap = componentDao.selectComponentMapByRequestIds(Utils.list2string(requestIds));

            // 按日期分组
            Map<String, List<Request>> requestDateMap = getRequestDateMap(requests);

            for (Map.Entry<String, List<Request>> dateEntry : requestDateMap.entrySet()) {
                List<Request> list = new ArrayList<>();
                String date = dateEntry.getKey();
                requests = dateEntry.getValue();

                Map<Integer, List<Request>> requestApplicantMap = getRequestApplicantMap(requests);

                for (Map.Entry<Integer, List<Request>> applicantEntry : requestApplicantMap.entrySet()) {
                    Integer applicant = applicantEntry.getKey();
                    requests = applicantEntry.getValue();

                    Map<Integer, Request> templateCostMap = new HashMap<>();
                    for (Request request : requests) {
                        Template template = templateMap.get(ancestorIdMap.get(request.getTemplateId()));
                        if (!templateCostMap.containsKey(template.getAncestorId())) {
                            templateCostMap.put(template.getAncestorId(), getRequest(applicant, template));
                        }
                        Request req = templateCostMap.get(template.getAncestorId());
                        BigDecimal cost = calculateCost(request, componentMap.get(request.getRequestDkey()));
                        req.setTotalCosts(req.getTotalCosts().add(cost));
                    }
                    list.addAll(templateCostMap.values());
                }

                CostPeriod costPeriod = new CostPeriod();
                costPeriod.setDatetime(date);
                costPeriod.setList(list);
                result.add(costPeriod);
            }
            return result;
        } catch (Throwable e) {
            throw ErrorUtils.throwError(e, logger);
        } finally {
            DBUtils.release(connection);
        }
    }

    private Request getRequest(Integer applicant, Template template) {
        Request request = new Request();
        request.setApplicant(applicant);
        request.setAncestorId(template.getAncestorId());
        request.setDefaultType(template.getDefaultType());
        request.setTemplateColor(template.getTemplateColor());
        request.setTemplateId(template.getTemplateId());
        request.setTemplateName(template.getTemplateName());
        request.setVersion(template.getVersion());
        request.setTotalCosts(new BigDecimal(0));
        return request;
    }

    private Map<Integer, List<Request>> getRequestApplicantMap(List<Request> requests) {
        Map<Integer, List<Request>> requestApplicantMap = new HashMap<>();
        for (Request request : requests) {
            if (!requestApplicantMap.containsKey(request.getApplicant())) {
                requestApplicantMap.put(request.getApplicant(), new ArrayList<>());
            }
            requestApplicantMap.get(request.getApplicant()).add(request);
        }
        return requestApplicantMap;
    }

    private Map<String, List<Request>> getRequestDateMap(List<Request> requests) {
        Map<String, List<Request>> requestDateMap = new HashMap<>();
        for (Request request : requests) {
            String date = request.getFinallyConfirmedTime();
            if (!requestDateMap.containsKey(date)) {
                requestDateMap.put(date, new ArrayList<>());
            }
            requestDateMap.get(date).add(request);
        }
        return requestDateMap;
    }

    @Override
    public BigDecimal getPeopleApprovalCostPeriod(Request query, User user) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            TemplateDao templateDao = new TemplateDaoImpl(connection);
            ComponentDao componentDao = new ComponentImpl(connection);

            //获得关联成本分析的所有模板
            query.setCompanyId(user.getCompanyId());
            List<Template> templates = templateDao.selectCostAnalysisTemplates(query);
            BigDecimal totalCost = BigDecimal.ZERO;

            if (Utils.isEmpty(templates)) {
                return totalCost;
            }

            List<Request> requests = templateDao.getRequestByTemplatesWithSearchRangeAndCurrentMonths(templates, query);
            if (Utils.isEmpty(requests)) {
                return totalCost;
            }

            List<Integer> requestIds = RequestUtils.getRequestIds(requests);
            Map<Integer, List<TemplateComponent>> componentMap = componentDao.selectComponentMapByRequestIds(Utils.list2string(requestIds));

            for (Request request : requests) {
                BigDecimal cost = calculateCost(request, componentMap.get(request.getRequestDkey()));
                totalCost = totalCost.add(cost);
            }

            return totalCost.setScale(2, RoundingMode.HALF_UP);
        } catch (Throwable e) {
            throw ErrorUtils.throwError(e, logger);
        } finally {
            DBUtils.release(connection);
        }
    }

    @Override
    public List<Template> getUsedTemplateInDaysByUser(Template template, List<String> days, List<User> userList, int type) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            TemplateDao templateDao = new TemplateDaoImpl(connection);
            List<Template> list = templateDao.getTemplateFamilyByTemplates(template, userList.get(0));
            List<Integer> ids = null;
            if (type == 0) {
                ids = templateDao.getUsedTemplateIdsInDaysByTemplateIds(list, days);             // 导出全公司申请的
            } else if (type == 1) {
                ids = templateDao.getUsedTemplateIdsInDaysByTemplateIdsAndUser(list, days, userList.get(0));    // 导出该用户申请的
            } else if (type == 2) {
                ids = templateDao.getUsedTemplateIdsInDaysByTemplateIdsAndUsers(list, days, userList);  // 导出某些人申请的
            }

            List<Template> usedTemplates = new ArrayList<>();
            if (Utils.isEmpty(ids)) {
                return usedTemplates;
            }
            for (Template t : list) {
                if (ids.contains(t.getTemplateId())) {
                    usedTemplates.add(t);
                }
            }

            if (ListHelper.isNotNullEmpty(usedTemplates)) {
                String templateIds = getTemplateIds(usedTemplates);
                List<Template> templates = templateDao.getTemplateGroupJson(templateIds);

                for (Template usedTemplate : usedTemplates) {
                    for (Template template1 : templates) {
                        if (usedTemplate.getTemplateId() == template1.getTemplateId()) {
                            usedTemplate.setComponentGroupJson(template1.getComponentGroupJson());
                            break;
                        }
                    }
                }
            }

            return usedTemplates;
        } catch (Throwable e) {
            throw ErrorUtils.throwError(e, logger);
        } finally {
            DBUtils.release(connection);
        }
    }

    private String getTemplateIds(List<Template> usedTemplates) {
        List<Integer> templateIds = new ArrayList<>(usedTemplates.size());

        for (Template usedTemplate : usedTemplates) {
            templateIds.add(usedTemplate.getTemplateId());
        }

        return ListHelper.list2string(templateIds);
    }

    @Override
    public List<Template> getTemplateUsed(User user) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            TemplateDao templateDao = new TemplateDaoImpl(connection);

            return templateDao.getTemplateUsed(user);
        } catch (Throwable e) {
            throw ErrorUtils.throwError(e, logger);
        } finally {
            DBUtils.release(connection);
        }
    }

    @Override
    public List<Template> getTemplateCcToMe(User user) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            TemplateDao templateDao = new TemplateDaoImpl(connection);
            CcDao ccDao = new CcDaoImpl(connection);
            List<Integer> requestIds = ccDao.selectUserCcRequestIds(user.getCompanyId(), user.getCompanyInfoId());

            return templateDao.selectLastTemplateByRequestIds(Utils.list2string(requestIds));
        } catch (Throwable e) {
            throw ErrorUtils.throwError(e, logger);
        } finally {
            DBUtils.release(connection);
        }
    }

    @Override
    public List<Comment> getCommentMessage(Request request, User needCompanyId) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            TemplateDao templateDao = new TemplateDaoImpl(connection);

            List<Comment> list = templateDao.getCommentMessage(request, needCompanyId);
            Set<Integer> contactIds = new HashSet<>();
            for (Comment comment : list) {
                contactIds.add(comment.getCreateId());
            }
            if (Utils.isNotEmpty(contactIds)) {
                UserServicePrx userServicePrx = ServantUtils.getObject(UserServicePrx.class);
                List<User> userList = userServicePrx.getUserListByContactIds(Utils.collection2string(contactIds));
                Map<Integer, String> map = new HashMap<>();
                for (User user : userList) {
                    map.put(user.getContactId(), user.getContactName());
                }
                for (Comment comment : list) {
                    comment.setCrtName(map.get(comment.getCreateId()));
                }
            }

            return list;
        } catch (Throwable e) {
            throw ErrorUtils.throwError(e, logger);
        } finally {
            DBUtils.release(connection);
        }
    }

    @Override
    public void saveGeneralRequestFlow(GeneralRequest request, User user) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            TemplateDao templateDao = new TemplateDaoImpl(connection);
            DBUtils.begin(connection);

            GeneralRequest generalRequest = new GeneralRequest();
            generalRequest.setProject(request.getProject());
            generalRequest.setSpecificId(request.getSpecificId());
            generalRequest = templateDao.getCompanyGeneralFlowSettings(generalRequest, user);

            int generalFlowId = templateDao.saveGeneralRequestFlow(request, user);
            if ("Condition".equals(request.getRequestFlow())) {
                if (generalRequest.getGeneralFlowId() != 0) {
                    request.setGeneralFlowId(generalRequest.getGeneralFlowId());
                    templateDao.disableGeneralRequestConditionFlow(request, user);
                }
                request.setGeneralFlowId(generalFlowId);
                templateDao.saveGeneralRequestConditionFlow(request, user);
            }

            DBUtils.commit(connection);
        } catch (Throwable e) {
            throw ErrorUtils.throwError(e, logger);
        } finally {
            DBUtils.release(connection);
        }
    }

    @Override
    public GeneralRequest getGeneralRequestFlow(GeneralRequest request, User user) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            TemplateDao templateDao = new TemplateDaoImpl(connection);
            GeneralRequest generalRequest = new GeneralRequest();
            generalRequest.setProject(request.getProject());
            generalRequest.setSpecificId(request.getSpecificId());

            return templateDao.getCompanyGeneralFlowSettings(generalRequest, user);
        } catch (Throwable e) {
            throw ErrorUtils.throwError(e, logger);
        } finally {
            DBUtils.release(connection);
        }
    }

    @Override
    public List<Request> siftingRequestRelatedToCostAnalysis(List<Request> list) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            TemplateDao templateDao = new TemplateDaoImpl(connection);

            List<Integer> companies = new LinkedList<>();
            for (Request r : list) {
                if (!companies.contains(r.getCompanyId())) {
                    companies.add(r.getCompanyId());
                }
            }

            //获得关联成本分析的所有模板
            List<Template> templates = templateDao.getRelatedToCostAnalysisTemplateListInTheseCompanies(companies);
            List<Request> rtList = new ArrayList<>();
            //获得父辈模板
            if (templates.size() != 0) {
                templates = templateDao.getTemplateFamilyByTemplates(templates);
                //根据这些模板来计算成本
                //step.2 获得这个人的这些模板的审批，在一定范围内
                rtList = templateDao.siftingRequestRelatedToCostAnalysis(templates, list);
            }
            return rtList;
        } catch (Throwable e) {
            throw ErrorUtils.throwError(e, logger);
        } finally {
            DBUtils.release(connection);
        }
    }

    @Override
    public List<Template> getTemplateDetailByTemplateIdList(List<Integer> templateIdList) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            TemplateDao templateDao = new TemplateDaoImpl(connection);

            /* 批量获取需要导出的模板详情 */
            return templateDao.getTemplateDetailByTemplateIdList(templateIdList);
        } catch (Throwable e) {
            throw ErrorUtils.throwError(e, logger);
        } finally {
            DBUtils.release(connection);
        }
    }


    @Override
    public List<Template> getMyCompanysGeneralTemplateList(User user) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            TemplateDao templateDao = new TemplateDaoImpl(connection);
            return templateDao.getCompanyGeneralTemplateList(user);
        } catch (Throwable e) {
            throw ErrorUtils.throwError(e, logger);
        } finally {
            DBUtils.release(connection);
        }
    }

}
